package com.cultraview;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Function;
import java.util.function.ToDoubleFunction;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;

import org.opencv.core.Rect;

public class SummaryRectsInfo {
	private int x;
	private int y;
	private int mWidth;
	private int mHeight;
	private SummaryType mSummaryType;
	private final static int summaryTolerance = 10;
	private ArrayList<Rect> mRects = new ArrayList<>();
	

    public enum SummaryType {
    	SUMMARY_TYPE_X(0),
    	SUMMARY_TYPE_Y(1),
    	SUMMARY_TYPE_WIDTH_HEIGHT(5);

        private int val;

        SummaryType(int val) {
            this.val = val;
        }

        public int toInt() {
            return this.val;
        }
    }

	public SummaryRectsInfo(int x, int y, int width, int height, SummaryType summaryType) {
		super();
		this.x = x;
		this.y = y;
		this.mWidth = width;
		this.mHeight = height;
		this.mSummaryType = summaryType;
	}

	public SummaryRectsInfo(Rect rect, SummaryType summaryType) {
		super();
		this.x = rect.x;
		this.y = rect.y;
		this.mWidth = rect.width;
		this.mHeight = rect.height;
		this.mSummaryType = summaryType;
		this.mRects.add(rect);
		// System.out.println("creat height:" + mHeight + " width:" + mWidth);
	}

	public boolean containsInSummary(Rect rect) {
		// System.out.println("x height:" + rect.height + " " + mHeight +
		// " x width:" + rect.width + " " + mWidth);
		if(mSummaryType == SummaryType.SUMMARY_TYPE_WIDTH_HEIGHT) {
			if (Math.abs(rect.height - mHeight) < summaryTolerance
					&& Math.abs(rect.width - mWidth) < summaryTolerance) {
				return true;
			}
		} else if(mSummaryType == SummaryType.SUMMARY_TYPE_Y) {
			if (Math.abs(rect.y - y) < summaryTolerance
					&& Math.abs(rect.y - y) < summaryTolerance) {
				return true;
			}
		} else if(mSummaryType == SummaryType.SUMMARY_TYPE_X) {
			if (Math.abs(rect.x - x) < summaryTolerance
					&& Math.abs(rect.x - x) < summaryTolerance) {
				return true;
			}
		}
		return false;
	}

	public void addRect(Rect rect) {
		mRects.add(rect);
	}

	public int size() {
		return mRects.size();
	}

	public int getX() {
		return x;
	}
	
	public int getY() {
		return y;
	}
	public int getWidth() {
		return mWidth;
	}

	public int getHeight() {
		return mHeight;
	}
	
	public int getChildCount(){
		return mRects.size();
	}
	public Rect getRect(int index) {
		return mRects.get(index);
	}

	public String printinfo(boolean showdetails) {
		StringBuffer sb = new StringBuffer();
		for (Rect rect : mRects) {
			sb.append("\n\t");
			sb.append(rect.toString());
		}
		return "SummaryInfo] Type:" + mSummaryType.name() + "[x,y width*height]: ["+ x + "," + y + " " +mWidth+"*"+mHeight+"]"+ " Thd:abs" + summaryTolerance + " counts:"
				+ mRects.size() + ((showdetails?sb.toString():""));
	}

	public static Comparator widthComparator = new Comparator() {

		@Override
		public int compare(Object arg0, Object arg1) {
			// TODO Auto-generated method stub
			return ((((SummaryRectsInfo) arg0).mWidth < ((SummaryRectsInfo) arg1).mWidth ? 1
					: (((SummaryRectsInfo) arg0).mWidth == ((SummaryRectsInfo) arg1).mWidth ? 0 : -1)));
		}

	};
	
	public static Comparator heighComparator = new Comparator() {

		@Override
		public int compare(Object arg0, Object arg1) {
			// TODO Auto-generated method stub
			return ((((SummaryRectsInfo) arg0).mHeight < ((SummaryRectsInfo) arg1).mHeight ? 1
					: (((SummaryRectsInfo) arg0).mHeight == ((SummaryRectsInfo) arg1).mHeight ? 0 : -1)));
		}

	};
	
	public static ArrayList<SummaryRectsInfo> summaryRect(ArrayList<Rect> rects,SummaryType summaryType) {
		Rect rect;
		ArrayList<SummaryRectsInfo> summaryinfos = new ArrayList<>();
		for (int i = 0; i < rects.size(); i++) {
			rect = rects.get(i);
			if (summaryinfos.size() == 0) {
				SummaryRectsInfo info = new SummaryRectsInfo(rect, summaryType);
				summaryinfos.add(info);
				// System.out.println("1info:" + info.printinfo());
			} else {
				// System.out.println("summaryinfos size:" +
				// summaryinfos.size());
				boolean summarised = false;
				for (int j = 0; j < summaryinfos.size(); j++) {
					if (summaryinfos.get(j).containsInSummary(rect)) {
						summaryinfos.get(j).addRect(rect);
						summarised = true;
						break;
					}
				}
				if (!summarised) {
					SummaryRectsInfo info = new SummaryRectsInfo(rect, summaryType);
					summaryinfos.add(info);
					// System.out.println("2info:" + info.printinfo());
				}
			}
		}
		return summaryinfos;
	}
}
